﻿(function($, $$){
	var undefined;
	
	/*
		utilities		***
	*/
	
	$$.beforeOverride = function(propertyName) {
		var newProp = this.constructor.prototype[propertyName];
		delete this.constructor.prototype[propertyName];
		var oldProp = this[propertyName];
		
		this.constructor.prototype[propertyName] = newProp;
		return oldProp;
	};
	
	/*
		feature tabs		***
	*/
	$$.tabs = function(){
		if (this instanceof $$.dialog)
			this.initTab (this._dom.find('div.jkui-tabs'));
	};
	$$.tabs.prototype.initTab = function(selector){
	
		var tabUl = this.tabUl = $(selector).attr('jkuiType', 'tabs').children('ul').attr('jkuiType', 'jkui-tabs-tabs');
		var tabPanel = this.tabPanel = tabUl.nextAll('div').attr('jkuiType', 'tabPanel').addClass('jkui-tab-panel');
		
		this._assignEvents();
		
		return this;
	};
	
	$$.tabs.prototype.showTab = function(selector){
		if (typeof selector == 'number') 
			$(this.tabUl.find('> li > a')[selector]).click();
		else
			this.tabUl.find(selector).click();
		return this;
	};
	
	$$.tabs.prototype._assignEvents = function(){
		var THIS = this;
		
		$$.each(THIS.tabUl.children('li'), function(i){
			$(this).find('a').click(function(){
				if (THIS.trigger('contentchanging')) {
					
					THIS.tabUl.find('> li > a').removeClass('jkui-tab-active');
					
					$(this).addClass('jkui-tab-active');
					
					THIS.tabPanel.hide();
					$(THIS.tabPanel[i]).show();
					
					THIS.trigger('contentchanged')
				}
				return false;
			});
		});
	};
	
	/*
		feature asyncronized		***
	*/
	
	$$.asyncronized = {
		load: function(callback) {
			if (this.trigger('loading') && !this.isLoaded) {
				
				this._load(function(){
					this.hide();	
					this.isLoaded = true;
					this.trigger('loaded');
				});
			}
			
			return this;
		},
		_load: function(callback) {
			$$.assert(false, '_load must be overridden');
		},
		show: function() {
			if (this.trigger('showing') && this.isHidden) {
				
				this._show($$.bind(function(){
					this.isHidden = false;
					this.trigger('shown');
				},this));
			}
			
			return this;
		},
		_show: function() {
			$$.assert(false, '_show must be overridden');
		},
		hide: function() {
			if (this.trigger('hiding') && !this.isHidden) {
				
				this._hide($$.bind(function(){
					this.isHidden = true;
					this.trigger('hidden');
				},this));
				
			}
			
			return this;
		},
		_hide: function(callback) {
			$$.assert(false, '_hide must be overridden');
		}
	};
	
	/*
		feature fancyWindow		***
	*/
	
	$$.fancyWindow = {
		_show: function(callback){
			var oldShow = $$.beforeOverride.call(this, '_show');
			if (this.props.morphStart) {
				var morphStart = $(this.props.morphStart);
				
				this._dom.show();
				this.adjustGeometry();
				
				var geometryStart = $.extend(morphStart.offset(), {height: morphStart.height(), width: morphStart.width(), opacity: 0.2});
				var geometryEnd = $.extend(this._dom.offset(), {height: this._dom.height(), width: this._dom.width(), opacity: 0.6});
				
				this._dom.hide();
				
				var morpher = this._dom.find('[jkuiType=windowBackground]').clone().appendTo('body').css(
					$.extend(geometryStart, {zIndex: 32767}));
				
				this.overlay.show();
				morpher.animate (geometryEnd, 500, $$.bind(function() {
					morpher.remove();
					oldShow.apply(this, arguments);
					callback();
				},this));
			} else {
				oldShow.apply(this, arguments);
				callback();
			}
		},
		_hide: function(callback){
			var oldHide = $$.beforeOverride.call(this, '_hide');
			if (this.props.morphStart) {
				var morphStart = $(this.props.morphStart);
				
				var geometryStart = $.extend(morphStart.offset(), {height: morphStart.height(), width: morphStart.width(), opacity: 0.2});
				var geometryEnd = $.extend(this._dom.offset(), {height: this._dom.height(), width: this._dom.width()});
				
				var morpher = this._dom.find('[jkuiType=windowBackground]').clone().appendTo('body').css(
					$.extend(geometryEnd, {zIndex: 32767, opacity: 1}));
				
				this.overlay.hide();
				this._dom.hide();
				morpher.animate (geometryStart, 500, $$.bind(function() {
					morpher.remove();
					oldHide.apply(this, arguments);
					callback();
				},this));
			} else {
				oldHide.apply(this, arguments);
				callback();
			}
		},
		morphStart: function(m) {
			//getter
			if (!arguments.length)
				return this.props.morphStart;
			
			//setter
			this.props.morphStart = m;
		}
	};
})(jQuery, jkui);
